/*
 * ShadowSpace.h
 *
 *  Author:
 */

#ifndef SHADOWSPACE_H_
#define SHADOWSPACE_H_

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <inttypes.h>
#include <list>
#include <map>
#include "contest_interface.h"


struct NewRecord;
struct ModifiedRecord;

class ShadowSpace {
private:
    std::list<NewRecord *> addedRecords;
    std::list< Iterator **> readingIterators;
    // TODO change to uint64_t
    std::map<unsigned long, ModifiedRecord *> modifiedRecords;

public:
    ShadowSpace();
    ~ShadowSpace();

    // Used to update the Iterator retrieved by the getRecords method
    // the Iterator will be stored in the ShadowSpace, so each time that
    // another record is added to the ShadowSpace, the modification is
    // reflected to all Iterator that contain the record in its range
    ErrorCode UpdateIteratorList(Iterator ** recordsGotten);

    // Methods used to change the addedRecords list
    ErrorCode InsertNewRecordList(Record *record);
    ErrorCode UpdateNewRecordList(Record *record, Block *new_payload, uint8_t flags);
    ErrorCode DeleteNewRecordList(Record *record, uint8_t flags);

    // Methods used to add the results of canUpdate and canDelete in the ShadowSpace
    ErrorCode UpdateModifiedList(Iterator ** dbRecords, Record * matchingRecord, Block * newPayload, uint8_t flags);
    ErrorCode DeleteModifiedList(Iterator ** dbRecords, Record * matchingRecord, uint8_t flags);

    // Check if a valid record is present in the ShadowSpace
    bool checkExistance(Record *record, uint8_t flags);

    // Returns an Iterator with all the records that should be added to db
    ErrorCode getNewRecords(Iterator ** it);

    // Returns an Iterator with all the records that should be deleted from db
    ErrorCode getRecordsToBeDeleted(Iterator ** it);

    // TODO change Iterator to other object.
    // Returns an Iterator with all the records that should be updated in db
    ErrorCode getRecordsToBeUpdated(std::list<ModifiedRecord*> ** recordsToBeUpdated);

    // Used to free the memory of the ShadowSpace
    // this method is called by the destructor, and
    // it can also be called by the owner of the ShadowSpace
    void CleanSpace();
};

struct NewRecord {
    Record * value;

    NewRecord(Record * _value) {
        this->value = _value;
    }

    ~NewRecord() {
        this->value = NULL;
    }
};

struct ModifiedRecord {
    Record * valueInDb;
    Record * newValue;

    bool updated;
    bool deleted;

    ModifiedRecord(Record * recordInDb) {
        this->valueInDb = recordInDb;
        this->newValue = NULL;

        this->updated = false;
        this->deleted = true;
    }

    ModifiedRecord(Record * recordInDb, Record * _newValue) {
        this->valueInDb = recordInDb;
        this->newValue = _newValue;

        this->updated = true;
        this->deleted = false;
    }

    ~ModifiedRecord() {
        this->valueInDb = NULL;
        this->newValue = NULL;

        this->updated = false;
        this->deleted = false;
    }
};

#endif /* SHADOWSPACE_H_ */
